(function() {

  const PENDING = 'pending'
  const FULFILLED = 'fulfilled'
  const REJECTED = 'rejected'

  /* 
    Promise类
    excutor:执行器函数(同步)
  */
  class Promise {
    constructor(excutor) {
      const _this = this
      this.status = PENDING // promise实例对象的状态，初始值为pending
      this.data = undefined // 存储结果数据的属性
      this.callbacks = [] // 回调函数，每个元素的数据解构： { onResolved() {}, onRejected() {} }

      // 触发成功回调
      function resolve(value) {
        // 当前状态不是pending，结束
        if (_this.status !== PENDING) return false
        // 修改当前状态为fulfilled
        _this.status = FULFILLED
        // 保存数据结果
        _this.data = value
        // 如果由待执行的回调函数，立即异步执行回调函数的onResolved
        if (_this.callbacks.length) {
          setTimeout(() => {
            _this.callbacks.forEach(callbackObj => {
              callbackObj.onResolved(value)
            })
          })
        }
      }

      // 触发失败回调
      function reject(reason) {
        // 当前状态不是pending，结束
        if (_this.status !== PENDING) return false
        // 修改当前状态为rejected
        _this.status = REJECTED
        // 保存数据结果
        _this.data = reason
        // 如果有待执行的回调函数，立即异步执行回调函数的onRejected
        if (_this.callbacks.length) {
          setTimeout(() => {
            _this.callbacks.forEach(callbackObj => {
              callbackObj.onRejected(reason)
            })
          })
        }
      }

      // 处理执行器异常
      try {
        excutor(resolve, reject)
      } catch (error) {
        reject(error)
      }
    }
    /* 
      then方法
      指定成功和失败的回调
      返回一个promise
    */
    then(onResolved, onRejected) {
      const _this = this

      onResolved = typeof onResolved === 'function' ? onResolved : value => value // 向下传递value
      // 指定默认的失败回调onRejected（实现异常传透的关键）
      onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

      return new Promise((resolve, reject) => {
        // 调用指定回调函数处理,根据执行结果，改变return的promise的状态
        function handle(callback) {
          /* 
            1. 如果抛出异常，return的Promise的结果就是失败的，reason就是error
            2. 如果返回的结果不是promise类型，return的Promise的结果就是成功的，value就是该返回的结果
            3. 如果是promise，return的Promise的结果就是该promise的结果
          */
          try {
            const result = callback(_this.data)
            if (result instanceof Promise) {
              // 3. 返回的结果是promise，return的Promise的结果就是该promise的结果
              result.then(
                value => resolve(value),
                reason => reject(reason)
              )
              // result.then(resolve, reject)
            } else {
              // 2. 返回的结果不是promise类型，return的Promise的结果就是成功的，value就是该返回的结果
              resolve(result)
            }
          } catch (error) {
            // 1. 抛出异常，return的Promise的结果就是失败的，reason就是error
            reject(error)
          }
        }
        // 状态还没改变，先将回调函数存储起来，用于状态改变时调用
        if (this.status === PENDING) {
          this.callbacks.push({
            onResolved () {
              handle(onResolved)
            },
            onRejected () {
              handle(onRejected)
            }
          })
        } else if (this.status === FULFILLED) {
          // 状态是fulfilled，异步执行成功回调
          setTimeout(() => {
            handle(onResolved)
          })
        } else {
          // 状态是rejected，异步执行失败回调
          setTimeout(() => {
            handle(onRejected)
          })
        }
      })
    }

    /* 
      catch方法
      指定失败的回调
      返回一个promise
    */
    catch(onRejected) {
      return this.then(undefined, onRejected)
    }

    /* 
      Promise的静态方法resolve
      返回一个指定value的成功/失败的promise
    */
    static resolve = function(value) {
      return new Promise((resolve, reject) => {
        // value是一个promise
        if (value instanceof Promise) {
          value.then(resolve, reject)
        } else { // value不是一个promise
          resolve(value)
        }
      })
    }

    /* 
      Promise的静态方法reject
      返回一个指定reason的失败的promise
    */
    static reject = function(reason) {
      return new Promise((resolve, reject) => {
        reject(reason)
      })
    }

    /* 
      Promise的静态方法all
      返回一个promise，当多有promise都成功时才成功，有一个失败则失败
    */
    static all = function(promises) {
      // 定义一个指定长度的数组，用于存储resolve的值
      const values = new Array(promises.length)
      // 计数，用于记录成功的promise次数
      let resolveCount = 0
      return new Promise((resolve, reject) => {
        promises.forEach((p, index) => {
          Promise.resolve(p).then(
            value => {
              values[index] = value
              resolveCount ++
              // 如果全部都成功了，将返回的promise改为成功
              if (resolveCount === promises.length) {
                resolve(values)
              }
            },
            // 有一个promise失败，将返回的promise改为失败
            reason => {
              reject(reason)
            }
          )
        })
      })
    }

    /* 
      Promise的静态方法race
      返回一个promise，其结果由第一 个完成的promise决定
    */
    static race = function(promises) {
      return new Promise((resolve, reject) => {
        promises.forEach(p => {
          Promise.resolve(p).then(
            // 有一个promise成功，将返回的promise改为成功
            value => {
              resolve(value)
            },
            // 有一个promise失败，将返回的promise改为失败
            reason => {
              reject(reason)
            }
          )
        })
      })
    }
  }
  // 暴露Promise
  window.Promise = Promise
})()